<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint"
	xmlns:ext="urn:flexdoc.api.xsltextensions" exclude-result-prefixes="ext">
  <!-- The namespace 'urn:flexdoc.api.xsltextensions' maps to an extension-object which enriches the possibilities of xslt.
  This does however make it (virtually) impossible to run the xslt in a different environment than Visual Studio. -->
  
	<xsl:param name="data"/>
	<xsl:param name="dataNsPrefix"/>
	<xsl:param name="dataNs"/>
	
	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no"/>
	
	<!-- Root element renders the process-instruction 'mso-application' -->
	<xsl:template match="/">
		<xsl:copy>
			<xsl:apply-templates select="@*|node()">
				<xsl:with-param name="datacontext" select="$data" />
				<xsl:with-param name="listindex" select="-1"/>
			</xsl:apply-templates>
		</xsl:copy>
	</xsl:template>

	<!-- Unknown elements are simply copied -->
	<xsl:template match="*">
		<xsl:param name="datacontext" />
		<xsl:param name="listindex" />
		<xsl:copy>
			<xsl:apply-templates select="@*|node()">
				<xsl:with-param name="datacontext" select="$datacontext" />
				<xsl:with-param name="listindex" select="$listindex"/>
			</xsl:apply-templates>
		</xsl:copy>
	</xsl:template>

	<!-- Attributes, textnodes, etc are simply copied -->
	<xsl:template match="@*|text()|comment()|processing-instruction">
		<xsl:copy-of select="."/>
	</xsl:template>
	
	<!-- Defines the datacontext for its child nodes -->
  <xsl:template match="w:customXml[@w:uri = 'urn:fleXdoc' and @w:element='UseContext']">
    <xsl:param name="datacontext" />
    <xsl:param name="listindex" />

    <xsl:variable name="path" select="w:customXmlPr/w:attr[@w:name='path']/@w:val" />

    <xsl:apply-templates select="node()">
      <xsl:with-param name="datacontext" select="ext:Select($datacontext, $path, $dataNsPrefix, $dataNs, &quot;UseContext&quot;)" />
      <xsl:with-param name="listindex" select="$listindex" />
    </xsl:apply-templates>
  </xsl:template>

  <!-- Conditional block (only rendered when condition (specified by 'test') evaluates to True) -->
  <xsl:template match="w:customXml[@w:uri = 'urn:fleXdoc' and @w:element='If']">
    <xsl:param name="datacontext" />
    <xsl:param name="listindex" />

    <xsl:variable name="test" select="w:customXmlPr/w:attr[@w:name='test']/@w:val" />

    <xsl:if test="ext:Evaluate($datacontext, $test, $dataNsPrefix, $dataNs, &quot;If&quot;)">
      <xsl:apply-templates select="node()">
        <xsl:with-param name="datacontext" select="$datacontext" />
        <xsl:with-param name="listindex" select="$listindex" />
      </xsl:apply-templates>
    </xsl:if>
  </xsl:template>

  <xsl:template match="w:customXmlPr">
    <!-- Never render -->
  </xsl:template>
	
	<!-- Repeats its content for all data-items that match the specified path -->
  <xsl:template match="w:customXml[@w:uri = 'urn:fleXdoc' and @w:element='ForEach']">
    <xsl:param name="datacontext" />
    <xsl:param name="listindex" />

    <xsl:variable name="templatecontext" select="." />
    <xsl:variable name="path" select="w:customXmlPr/w:attr[@w:name='path']/@w:val" />
    <xsl:variable name="sortSelect">
      <xsl:variable name="sortSelectAttr" select="w:customXmlPr/w:attr[@w:name='sortSelect']/@w:val" />
      <xsl:choose>
        <xsl:when test="$sortSelectAttr">
          <xsl:value-of select="$sortSelectAttr" />
        </xsl:when>
        <xsl:otherwise />
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="sortOrder">
      <xsl:variable name="sortOrderAttr" select="w:customXmlPr/w:attr[@w:name='sortOrder']/@w:val" />
      <xsl:choose>
        <xsl:when test="$sortOrderAttr">
          <xsl:value-of select="$sortOrderAttr"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:text>ascending</xsl:text>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="sortDataType">
      <xsl:variable name="sortDataTypeAttr" select="w:customXmlPr/w:attr[@w:name='sortDataType']/@w:val" />
      <xsl:choose>
        <xsl:when test="$sortDataTypeAttr">
          <xsl:value-of select="$sortDataTypeAttr"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:text>text</xsl:text>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="sortCaseOrder">
      <xsl:variable name="sortCaseOrderAttr" select="w:customXmlPr/w:attr[@w:name='sortCaseOrder']/@w:val" />
      <xsl:choose>
        <xsl:when test="$sortCaseOrderAttr">
          <xsl:value-of select="$sortCaseOrderAttr"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:text>upper-first</xsl:text>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:choose>
      <xsl:when test="string($sortSelect) != ''">
        <xsl:for-each select="ext:Select($datacontext, $path, $dataNsPrefix, $dataNs, &quot;ForEach&quot;)">
          <xsl:sort select="ext:Evaluate(., $sortSelect, $dataNsPrefix, $dataNs, &quot;ForEach:Sort&quot;)" order="{$sortOrder}" data-type="{$sortDataType}" case-order="{$sortCaseOrder}" />
          <xsl:apply-templates select="$templatecontext/node()">
            <xsl:with-param name="datacontext" select="." />
            <xsl:with-param name="listindex" select="position()" />
          </xsl:apply-templates>
        </xsl:for-each>
      </xsl:when>
      <xsl:otherwise>
        <xsl:for-each select="ext:Select($datacontext, $path, $dataNsPrefix, $dataNs, &quot;ForEach&quot;)">
          <xsl:apply-templates select="$templatecontext/node()">
            <xsl:with-param name="datacontext" select="." />
            <xsl:with-param name="listindex" select="position()" />
          </xsl:apply-templates>
        </xsl:for-each>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
	
	<!-- Outputs the value of the specified path -->
  <xsl:template match="w:customXml[@w:uri = 'urn:fleXdoc' and @w:element='ValueOf']">
    <xsl:param name="datacontext" />
    <xsl:param name="listindex" />

    <xsl:variable name="path" select="w:customXmlPr/w:attr[@w:name='path']/@w:val" />
    <xsl:variable name="formatType" select="w:customXmlPr/w:attr[@w:name='format']/@w:val" />
    <xsl:variable name="formatString" select="w:customXmlPr/w:attr[@w:name='formatString']/@w:val" />
    <xsl:variable name="datanode" select="ext:Evaluate($datacontext, $path, $dataNsPrefix, $dataNs, &quot;ValueOf&quot;)" />
    <xsl:variable name="datavalue" select="ext:FormatNode($datanode, $formatType, $formatString)" />

    <!--<xsl:if test="ext:Trace(concat('listindex=',$listindex,',count(tr)=',count(ancestor::w:tr),',count(tc)=',count(ancestor::w:tc)))" />-->

    <xsl:choose>
      <xsl:when test="count(ancestor::w:tbl) &gt; 0">
        <!-- Inside a table -->
        <xsl:choose>
          <xsl:when test="count(ancestor::w:tr) = count(ancestor::w:tc)">
            <!-- Hosted inside a tablecell (tc) -->
            <xsl:choose>
              <xsl:when test="ancestor::w:p[not(descendant::w:tc)]">
                <!-- There's a paragraph in the ancestors at a lower level than the tc, so we are in a paragraph -->
                <xsl:call-template name="RenderDataItem">
                  <xsl:with-param name="dataitem" select="$datavalue" />
                </xsl:call-template>
              </xsl:when>
              <xsl:otherwise>
                <!-- Tablecell does not yet contain a paragraph -->
                <xsl:element name="p" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
                  <xsl:call-template name="RenderDataItem">
                    <xsl:with-param name="dataitem" select="$datavalue" />
                  </xsl:call-template>
                </xsl:element>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:when>
          <xsl:otherwise>
            <!-- Not hosted inside a tablecell, so include one in the output-->
            <xsl:element name="tc" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
              <xsl:element name="p" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
                <xsl:call-template name="RenderDataItem">
                  <xsl:with-param name="dataitem" select="$datavalue" />
                </xsl:call-template>
              </xsl:element>
            </xsl:element>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:when test="not(ancestor::w:p)">
        <!-- Not in a table, but a parent paragraph does not yet exists -->
        <xsl:element name="p" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
          <xsl:call-template name="RenderDataItem">
            <xsl:with-param name="dataitem" select="$datavalue" />
          </xsl:call-template>
        </xsl:element>
      </xsl:when>
      <xsl:otherwise>
        <!-- Not inside a table and a parent paragraph exists -->
        <xsl:call-template name="RenderDataItem">
          <xsl:with-param name="dataitem" select="$datavalue" />
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>

  </xsl:template>

  <!-- Outputs the value of the specified path -->
  <xsl:template match="w:customXml[@w:uri = 'urn:fleXdoc' and @w:element='ImgOf']">
    <xsl:param name="datacontext" />
    <xsl:param name="listindex" />

    <xsl:variable name="path" select="w:customXmlPr/w:attr[@w:name='path']/@w:val" />

    <xsl:choose>
      <xsl:when test="$path">
        <xsl:variable name="imgdata" select="ext:Evaluate($datacontext, $path, $dataNsPrefix, $dataNs, &quot;ImgOf&quot;)" />
        <xsl:choose>
          <xsl:when test="$imgdata">
            <xsl:copy>
              <xsl:apply-templates select="@*" />
              <xsl:element name="customXmlPr" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
                <xsl:copy-of select="w:customXmlPr/w:placeholder"/>
                <xsl:copy-of select="w:customXmlPr/w:attr[@w:name = 'path']"/>
                <xsl:element name="attr" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
                  <xsl:attribute name="name" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
                    <xsl:text>data</xsl:text>
                  </xsl:attribute>
                  <xsl:attribute name="val" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
                    <xsl:value-of select="$imgdata"/>
                  </xsl:attribute>
                </xsl:element>
              </xsl:element>
            </xsl:copy>
          </xsl:when>
          <xsl:otherwise>
            <xsl:copy-of select="." />
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:otherwise>
        <xsl:copy-of select="." />  
      </xsl:otherwise>
    </xsl:choose>

  </xsl:template>

  <!-- Outputs the value of the specified dataitem -->
  <xsl:template name="RenderDataItem">
    <xsl:param name="dataitem" />

    <xsl:element name="r" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
      <xsl:choose>
        <xsl:when test="(ancestor-or-self::*/preceding-sibling::w:r[1])[1]/w:rPr">
          <!-- If a previous run has properties (aka: has a style defined), then copy those. -->
          <xsl:copy-of select="(ancestor-or-self::*/preceding-sibling::w:r[1])[1]/w:rPr" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:if test="(ancestor-or-self::*/following-sibling::w:r[1])[1]/w:rPr">
            <!-- If a following run has properties (aka: has a style defined), then copy those. -->
            <xsl:copy-of select="(ancestor-or-self::*/following-sibling::w:r[1])[1]/w:rPr" />
          </xsl:if>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:element name="t" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
        <xsl:value-of select="$dataitem"/>
      </xsl:element>
    </xsl:element>
  </xsl:template>
	
</xsl:stylesheet>
